package com.hex.ds.hdtp.core.app.script.transfer.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.hex.ds.hdtp.core.app.common.page.PageData;
import com.hex.ds.hdtp.core.app.common.page.converter.IPageAndPageDtoConverter;
import com.hex.ds.hdtp.core.app.common.page.dto.PageDto;
import com.hex.ds.hdtp.core.app.common.util.FileEncodeUtil;
import com.hex.ds.hdtp.core.app.script.transfer.converter.IScriptConvertOptLogConverter;
import com.hex.ds.hdtp.core.app.script.transfer.converter.IScriptConvertTargetListConverter;
import com.hex.ds.hdtp.core.app.script.transfer.dto.request.ScriptConvertSourceListRequestDto;
import com.hex.ds.hdtp.core.app.script.transfer.dto.request.ScriptConvertTargetListRequestDto;
import com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertSourceListResponseDto;
import com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertTargetListResponseDto;
import com.hex.ds.hdtp.core.app.script.transfer.handler.IScriptVerifyHandlerService;
import com.hex.ds.hdtp.core.app.script.transfer.service.IScriptConvertOptLogService;
import com.hex.ds.hdtp.core.app.script.transfer.service.IScriptConvertTargetListService;
import com.hex.ds.hdtp.core.inf.common.page.Page;
import com.hex.ds.hdtp.core.inf.script.transfer.po.ScriptConvertSourceListPo;
import com.hex.ds.hdtp.core.inf.script.transfer.po.ScriptConvertTargetListPo;
import com.hex.ds.hdtp.core.inf.script.transfer.repository.IScriptConvertTargetListRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @Package: com.hex.ds.hdtp.core.app.script.transfer.service.impl
 * @ClassName ScriptConvertTargetListService
 * @Description: 脚本转换-转换后文件-业务接口实现
 * @Author: wz.li
 * @Date 2023/8/14 16:40
 * @Version v2.0.2
 **/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy, @Autowired})
public class ScriptConvertTargetListService implements IScriptConvertTargetListService {

    private final IScriptConvertTargetListRepository scriptConvertTargetListRepository;

    private final IPageAndPageDtoConverter pageAndPageDtoConverter;

    private final IScriptConvertTargetListConverter converter;

    private final IScriptConvertOptLogService scriptConvertOptLogService;

    private final IScriptConvertOptLogConverter scriptConvertOptLogConverter;

    private final IScriptVerifyHandlerService scriptVerifyHandlerService;

    /*
     * @Method: queryListByPage <br>
     * @Param: [scriptConvertTargetListRequestDto, pageDto] <br>
     * @Return: com.hex.ds.hdtp.core.app.common.page.PageData <br>
     * @Description：分页查询<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 16:47 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public PageData queryListByPage(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto, PageDto pageDto) {
        final Page<ScriptConvertTargetListPo> pageResult = scriptConvertTargetListRepository.queryListByPage(
                converter.toPo(scriptConvertTargetListRequestDto), pageAndPageDtoConverter.toPage(pageDto));
        List<ScriptConvertTargetListResponseDto> responseDtos = converter.toDTOListForPo(pageResult.getData());
        return new PageData(responseDtos, pageResult.getTotal());
    }

    /*
     * @Method: queryListByTaskId <br>
     * @Param: [convertTaskId] <br>
     * @Return: java.util.List<com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertTargetListResponseDto> <br>
     * @Description：获取指定转换任务的转换文件清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/14 20:31 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public List<ScriptConvertTargetListResponseDto> queryListByTaskId(String convertTaskId) {
        return converter.toDTOListForPo(scriptConvertTargetListRepository.queryListByTaskId(convertTaskId));
    }

    /*
     * @Method: queryById <br>
     * @Param: [pkId] <br>
     * @Return: com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertTargetListResponseDto <br>
     * @Description：根据主键查询<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 16:47 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public ScriptConvertTargetListResponseDto queryById(String pkId) {
        ScriptConvertTargetListResponseDto scriptConvertTargetList = converter.toDTOForPo(scriptConvertTargetListRepository.queryById(pkId));
        scriptConvertTargetList.setSourceFileContent(getFileContent(scriptConvertTargetList.getSourceFileAbsolutePath()));
        scriptConvertTargetList.setConvertFileContent(getFileContent(scriptConvertTargetList.getConvertFileAbsolutePath()));
        return scriptConvertTargetList;
    }

    /*
     * @Method: queryConvertHistoryCompareContent <br>
     * @Param: [crunSourceListPkId, histSourceListPkId, convertFileName] <br>
     * @Return: com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertTargetListResponseDto <br>
     * @Description：获取指定的转换历史文件对比内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 16:49 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public ScriptConvertTargetListResponseDto queryConvertHistoryCompareContent(String crunSourceListPkId,
                                                                                String histSourceListPkId,
                                                                                String convertFileName) {
        ScriptConvertTargetListPo crunScriptConvertTargetListPo = scriptConvertTargetListRepository.queryBySourceListIdAndConvertFileName(crunSourceListPkId, convertFileName);
        ScriptConvertTargetListPo histScriptConvertTargetListPo = scriptConvertTargetListRepository.queryBySourceListIdAndConvertFileName(histSourceListPkId, convertFileName);
        ScriptConvertTargetListResponseDto scriptConvertTargetList = converter.toDTOForPo(crunScriptConvertTargetListPo);
        scriptConvertTargetList.setSourceFileContent(getFileContent(crunScriptConvertTargetListPo.getConvertFileAbsolutePath()));
        scriptConvertTargetList.setConvertFileContent(getFileContent(histScriptConvertTargetListPo.getConvertFileAbsolutePath()));
        return scriptConvertTargetList;
    }

    /*
     * @Method: getFileContent <br>
     * @Param: [filePath] <br>
     * @Return: java.lang.String <br>
     * @Description：读取指定文件内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/15 18:50 <br>
     * @Version： V2.0.2<br>
     */
    private String getFileContent(String filePath) {
        String convertFileAbsolutePath = FilenameUtils.separatorsToUnix(filePath);
        if (FileUtil.exist(convertFileAbsolutePath)) {
            return FileUtil.readString(convertFileAbsolutePath, FileEncodeUtil.getFileEncode(convertFileAbsolutePath));
        }
        return "";
    }

    /*
     * @Method: add <br>
     * @Param: [scriptConvertTargetListRequestDto] <br>
     * @Return: java.lang.String <br>
     * @Description：新增<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/14 17:15 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public String add(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto) {
        final ScriptConvertTargetListPo scriptConvertTargetListPo = converter.toPo(scriptConvertTargetListRequestDto);
        if (scriptConvertTargetListRepository.add(scriptConvertTargetListPo) != 1) {
            throw new RuntimeException("新增脚本转换后文件记录失败");
        }
        return scriptConvertTargetListPo.getPkId();
    }

    /*
     * @Method: modifyById <br>
     * @Param: [scriptConvertTargetListRequestDto] <br>
     * @Return: void <br>
     * @Description：根据主键更新<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/15 9:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void modifyById(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto) {
        final ScriptConvertTargetListPo scriptConvertTargetListPo = converter.toPo(scriptConvertTargetListRequestDto);
        if (scriptConvertTargetListRepository.modifyById(scriptConvertTargetListPo) != 1) {
            throw new RuntimeException("更新脚本转换后文件记录失败");
        }
    }

    /*
     * @Method: removeByTaskId <br>
     * @Param: [convertTaskPkId] <br>
     * @Return: void <br>
     * @Description：根据转换任务删除<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 15:14 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void removeByTaskId(String convertTaskPkId) {
        scriptConvertTargetListRepository.removeByTaskId(convertTaskPkId);
    }

    /*
     * @Method: updateFileContent <br>
     * @Param: [scriptConvertTargetListRequestDto] <br>
     * @Return: void <br>
     * @Description：更新指定转换后文件内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:19 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void updateFileContent(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto) {
        // 1、备份文件内容
        String backUpPath = backUpConvertFile(scriptConvertTargetListRequestDto);
        // 2、更新文件内容
        toUpdateFileContent(scriptConvertTargetListRequestDto);
        // 3、添加操作记录
        addOperationRecord(scriptConvertTargetListRequestDto, backUpPath);
    }

    /*
     * @Method: reverify <br>
     * @Param: [pkId] <br>
     * @Return: void <br>
     * @Description：重新验证指定脚本<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/29 14:12 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void reverify(String pkId) {
        final ScriptConvertTargetListPo scriptConvertTargetListPo = new ScriptConvertTargetListPo();
        scriptConvertTargetListPo.setPkId(pkId).setEmptyTestStatus("TODO").setStartTime("").setEndTime("");
        scriptConvertTargetListRepository.modifyById(scriptConvertTargetListPo);
        scriptVerifyHandlerService.scriptVerifyHandler(queryById(pkId));
    }

    /*
     * @Method: backUpConvertFile <br>
     * @Param: [scriptConvertTargetListRequestDto] <br>
     * @Return: java.lang.String <br>
     * @Description：备份源文件<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:21 <br>
     * @Version： V2.0.2<br>
     */
    private String backUpConvertFile(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto) {
        String backupRelativePath = scriptConvertTargetListRequestDto.getConvertFilePath() + File.separator + "backup-file"
                + File.separator + DateUtil.current(false) + "_" + scriptConvertTargetListRequestDto.getConvertFileName();
        try {
            FileUtils.copyFile(new File(scriptConvertTargetListRequestDto.getConvertFileAbsolutePath()), new File(backupRelativePath));
        } catch (IOException e) {
            log.error("备份转换文件内容失败, 失败原因：{}", e.getMessage(), e);
        }
        return backupRelativePath;
    }

    /*
     * @Method: toUpdateFileContent <br>
     * @Param: [scriptConvertTargetListRequestDto] <br>
     * @Return: void <br>
     * @Description：更新文件内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:57 <br>
     * @Version： V2.0.2<br>
     */
    private void toUpdateFileContent(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto){
        FileUtil.writeString(scriptConvertTargetListRequestDto.getConvertFileContent(),
                scriptConvertTargetListRequestDto.getConvertFileAbsolutePath(),
                FileEncodeUtil.getFileEncode(scriptConvertTargetListRequestDto.getConvertFileAbsolutePath()));
    }

    /*
     * @Method: addOperationRecord <br>
     * @Param: [scriptConvertTargetListPo, backUpPath] <br>
     * @Return: void <br>
     * @Description：添加操作记录<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:43 <br>
     * @Version： V2.0.2<br>
     */
    public void addOperationRecord(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto, String backUpPath) {
        scriptConvertTargetListRequestDto.setConvertFileSize(FileUtil.size(new File(scriptConvertTargetListRequestDto.getConvertFileAbsolutePath())) + "");
        scriptConvertTargetListRepository.modifyById(converter.toPo(scriptConvertTargetListRequestDto));
        scriptConvertOptLogService.add(scriptConvertOptLogConverter.toScriptConvertOptLogRequestDto(scriptConvertTargetListRequestDto, backUpPath));
    }

    @Override
    public PageData querySuccessListByPage(ScriptConvertTargetListRequestDto scriptConvertTargetListRequestDto, PageDto pageDto) {
        final Page<ScriptConvertTargetListPo> pageResult = scriptConvertTargetListRepository.querySuccessListByPage(
                converter.toPo(scriptConvertTargetListRequestDto), pageAndPageDtoConverter.toPage(pageDto));
        List<ScriptConvertTargetListResponseDto> responseDtos = converter.toDTOListForPo(pageResult.getData());
        return new PageData(responseDtos, pageResult.getTotal());
    }
}
